﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using Microsoft.SharePoint.Utilities;
using Wagner.Utilities;

namespace Wagner.SharePoint.Utilities
{
	internal abstract class OperationBase
	{
		private Arguments myArgs;
		internal Arguments Args
		{
			get { return (myArgs == null) ? myArgs = new Arguments(Environment.GetCommandLineArgs()) : myArgs; }
		}
		
		internal static Version Version
		{
			get { return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; }
		}
		
		internal string LayoutsTempPath
		{
			get
			{
				// The SPUtility.GetGenericSetupPath returns the full local path to the "12" hive.
				// The following will return the fillowin path assuming SharePoint was intalled
				// on the C: drive:
				// C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\Temp
				return SPUtility.GetGenericSetupPath(@"TEMPLATE\LAYOUTS\Temp");
			}
		}
		
		private DirectoryInfo myLayoutsTemp;
		internal DirectoryInfo LayoutsTemp
		{
			get
			{
				if (myLayoutsTemp == null)
				{
					myLayoutsTemp = new DirectoryInfo(LayoutsTempPath);

					if (!myLayoutsTemp.Exists)
						myLayoutsTemp.Create();
				}
				return myLayoutsTemp;
			}
		}

		internal string IsapiPath
		{
			get { return SPUtility.GetGenericSetupPath(@"ISAPI"); }
		}

		internal string TempFolder
		{
			get { return (Args["temppath"] == null) ? Environment.CurrentDirectory + "\\Temp" : new DirectoryInfo(Args["temppath"]).FullName; }
		}

		internal string OutputFolder
		{
			get { return (Args["outpath"] == null) ? Environment.CurrentDirectory : new DirectoryInfo(Args["outpath"]).FullName; }
		}

		internal string ValidateParameter(string parmName, bool required, string defaultValue)
		{			
			// Throw an exception for required parameters
			if (required == true && Args[parmName] == null)
				throw new ArgumentException(string.Format("The -{0} parameter is required.", parmName));
			
			// Return the default value for missing optional parameters
			if (required == false && Args[parmName] == null)
				return defaultValue;
			
			// Return parameter value
			return Args[parmName];
		}

		internal int ValidateParameterAsInteger(string parmName, bool required, int defaultValue)
		{
			int value;

			// Throw an exception for required parameters
			if( required == true && Args[parmName] == null)
				throw new ArgumentException(string.Format("The -{0} parameter is required.", parmName));

			// Return the default value for missing optional parameters
			if (required == false && Args[parmName] == null)
				return defaultValue;

			// Validate the value provided
			if (!int.TryParse(Args[parmName], out value))
				throw new ArgumentException(string.Format("The -{0} parameter must be an integer value.", parmName));

			return value;
		}

		internal bool ValidateParameterAsBool(string parmName, bool required, bool defaultValue)
		{
			// Throw an exception for required parameters
			if (required == true && Args[parmName] == null)
				throw new ArgumentException(string.Format("The -{0} parameter is required.", parmName));

			// Return the default value for missing optional parameters
			if (required == false && Args[parmName] == null)
				return defaultValue;

			// Return parameter value
			return Args[parmName] != null;
		}

		internal void CleanUpFile(FileInfo file)
		{
			if (file != null)
				if (file.Exists)
				{
					// Remove ReadOnly and Hidden attributes, and then delete.
					RemoveReadOnly(file);
					file.Delete();
					// File does not always appear to be deleting, so try again.
					file.Refresh();
					file.Delete();
				}
		}

		internal void RemoveReadOnly(FileInfo file)
		{
			if (file.Exists)
			{
				// Remove ReadOnly and Hidden attributes, and then delete.
				file.Attributes = file.Attributes & ~(FileAttributes.Hidden | FileAttributes.ReadOnly);
			}
		}

		internal void SaveFile(string fileText, string filePath)
		{
			// Write contents to a file.
			StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8);
			writer.WriteLine(fileText);
			writer.Close();
		}

		internal string QuotedString(string text)
		{
			return string.Format(@"""{0}""", text);
		}

		internal string TempFilePath(string filename)
		{
			DirectoryInfo dir = new DirectoryInfo(TempFolder);
			if (!dir.Exists)
				dir.Create();

			return dir.FullName + "\\" + filename;
		}

		internal string OutputFilePath(string filename)
		{
			DirectoryInfo path = new DirectoryInfo(OutputFolder);
			if (!path.Exists)
				path.Create();

			return path.FullName + "\\" + filename;
		}

		internal void Log(Exception ex)
		{
			while (ex != null)
			{
				Console.WriteLine(ex.Message);

				if (Args["debug"] == "true")
					Console.WriteLine(ex.StackTrace);

				ex = ex.InnerException;
			}
		}

		/// <summary>
		/// This method must be overriden by the inheriting class.
		/// </summary>
		internal virtual void Run()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// This method must be overriden by the inheriting class.
		/// </summary>
		internal virtual string HelpSummary
		{
			get
			{
				return "HelpSummary method not implemented in " + this.ToString();
			}
		}

		/// <summary>
		/// This method must be overriden by the inheriting class.
		/// </summary>
		internal virtual string HelpDetail
		{
			get
			{
				return "HelpDetail method not implemented in " + this.ToString();
			}
		}

	}
}
